package com.huike.report.service.impl;

import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;

import com.huike.report.domain.vo.*;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.huike.business.mapper.TbBusinessMapper;
import com.huike.clues.domain.TbActivity;
import com.huike.clues.domain.TbAssignRecord;
import com.huike.clues.domain.TbClue;
import com.huike.clues.domain.vo.SubjectVo;
import com.huike.clues.mapper.TbClueMapper;
import com.huike.common.core.domain.entity.SysDept;
import com.huike.common.exception.BaseException;
import com.huike.common.exception.CustomException;
import com.huike.contract.domain.TbContract;
import com.huike.contract.mapper.TbContractMapper;
import com.huike.report.mapper.ReportMapper;
import com.huike.report.service.IReportService;
import lombok.extern.slf4j.Slf4j;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;

import java.util.stream.Collectors;

@Slf4j
@Service
public class ReportServiceImpl implements IReportService {
   @Autowired
    private ReportMapper reportMapper;
    @Autowired
    private TbClueMapper tbClueMapper; // 操作线索
    @Autowired
    private TbContractMapper tbContractMapper; // 操作合同
    @Autowired
    private TbBusinessMapper tbBusinessMapper; // 操作合同
    /**
     * *************看我看我**************
     * 传入两个时间范围，返回这两个时间范围内的所有时间，并保存在一个集合中
     * @param beginTime
     * @param endTime
     * @return
     * @throws ParseException
     */
    public static List<String> findDates(String beginTime, String endTime)
            throws ParseException {
        List<String> allDate = new ArrayList();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");

        Date dBegin = sdf.parse(beginTime);
        Date dEnd = sdf.parse(endTime);
        allDate.add(sdf.format(dBegin));
        Calendar calBegin = Calendar.getInstance();
        // 使用给定的 Date 设置此 Calendar 的时间
        calBegin.setTime(dBegin);
        Calendar calEnd = Calendar.getInstance();
        // 使用给定的 Date 设置此 Calendar 的时间
        calEnd.setTime(dEnd);
        // 测试此日期是否在指定日期之后
        while (dEnd.after(calBegin.getTime())) {
            // 根据日历的规则，为给定的日历字段添加或减去指定的时间量
            calBegin.add(Calendar.DAY_OF_MONTH, 1);
            allDate.add(sdf.format(calBegin.getTime()));
        }
        System.out.println("时间==" + allDate);
        return allDate;
    }



    /**
     * ************看我看我***********
     * 用我能少走很多路
     * 我是用来机选百分比的方法
      * @param all
     * @param num
     * @return
     */
    private BigDecimal getRadio(Integer all,Long num) {
        if(all.intValue()==0){
            return new BigDecimal(0);
        }
        BigDecimal numBigDecimal = new BigDecimal(num);
        BigDecimal allBigDecimal = new BigDecimal(all);
        BigDecimal divide = numBigDecimal.divide(allBigDecimal,4,BigDecimal.ROUND_HALF_UP);
        return divide.multiply(new BigDecimal(100));
    }

    /**
     * 漏斗统计
     * @param beginCreateTime
     * @param endCreateTime
     * @return
     */
    @Override
    public VulnerabilityMapVo getVulnerabilityMap(LocalDate beginCreateTime, LocalDate endCreateTime) {
        //线索数 tb_clue  sum 累加获得
        //1.根据时间获取线索数
        LocalDateTime beginTime = LocalDateTime.of(beginCreateTime, LocalTime.MIN);
        LocalDateTime endTime = LocalDateTime.of(endCreateTime, LocalTime.MAX);
//线索数
        Integer cluesNum = tbClueMapper.cluesNums(beginTime, endTime);
        //2.有效线索数  状态为1.2.6   select count(*) from tb_clue where status in 1 2 6, bengin ,end
        Integer effectiveCluesNums = tbClueMapper.effectiveCluesNums(beginTime, endTime);
        //3.商机数
        Integer businessNums = tbBusinessMapper.businessNums(beginTime, endTime);
        //4.合同数 ，状态为4  select count(*) from tb_contract where status =4 and create_time between #{beginTime} and  #{endTime}
        Integer contractNums = tbContractMapper.businessNums(beginTime, endTime);
        VulnerabilityMapVo vulnerabilityMapVo = VulnerabilityMapVo.builder()
                .cluesNums(cluesNum)
                .effectiveCluesNums(effectiveCluesNums)
                .businessNums(businessNums)
                .contractNums(contractNums).build();
        return vulnerabilityMapVo;
    }


    /**
     * 首页数据统计
     *
     * @return
     */
    @Override
    public IndexVo indexTodoInfo(LocalDate beginTime, LocalDate endTime) {
        log.info("service=================>beginCreateTime:{},endCreateTime:{}", beginTime, endTime);

        LocalDateTime beginCreateTime = LocalDateTime.of(beginTime, LocalTime.MIN);
        LocalDateTime endCreateTime = LocalDateTime.of(endTime, LocalTime.MAX);

        log.info("service beginCreateTime =================>beginCreateTime:{}", beginCreateTime);
        log.info("service endCreateTime =================>endCreateTime:{}", endCreateTime);

        Map map = new HashMap<>();
        //今日新增开始时间
        LocalDateTime nowBeginTime = LocalDateTime.of(endTime, LocalTime.MIN); //今日新增开始时间
        LocalDateTime nowEndTime = LocalDateTime.of(endTime, LocalTime.MAX); //今日新增结束时间
        map.put("beginCreateTime", nowBeginTime);
        map.put("endCreateTime", nowEndTime);
        Integer todayCluesNum = reportMapper.countCluesByMap(map);//今日新增线索数量
        Integer todayBusinessNum = reportMapper.countBusinessByMap(map);//今日新增上级数量
        Integer todayContractNum = reportMapper.countContractNumByMap(map);//今日新增客户数量
        Double todaySalesAmount = reportMapper.sumSalesAmountByMap(map);//今日新增销售额
        todaySalesAmount = (todaySalesAmount == null ? 0.0 : todaySalesAmount);

        map.put("beginCreateTime", beginCreateTime);
        map.put("endCreateTime", endCreateTime);
        Integer cluesNum = reportMapper.countCluesByMap(map);//线索数量
        Integer businessNum = reportMapper.countBusinessByMap(map);//商机数量
        Integer contractNum = reportMapper.countContractNumByMap(map);//新增客户数量
        Double salesAmount = reportMapper.sumSalesAmountByMap(map);//销售金额
        salesAmount = (salesAmount == null ? 0.0 : salesAmount);
        Integer tofollowedCluesNum = reportMapper.countFollowedClues();//待跟进线索数量
        Integer tofollowedBusinessNum = reportMapper.countFollowedBusinese();//待跟进商机数量
        Integer toallocatedCluesNum = reportMapper.countAllocatedClues();//待分配线索
        Integer toallocatedBusinessNum = reportMapper.countAllocatedBusiness();//带分配商机


        //封装返回数据
        IndexVo indexVo = new IndexVo();
        indexVo.setCluesNum(cluesNum);
        indexVo.setBusinessNum(businessNum);
        indexVo.setContractNum(contractNum);
        indexVo.setSalesAmount(salesAmount);

        indexVo.setTodayCluesNum(todayCluesNum);
        indexVo.setTodayBusinessNum(todayBusinessNum);
        indexVo.setTodayContractNum(todayContractNum);
        indexVo.setTodaySalesAmount(todaySalesAmount);

        indexVo.setTransferNum(tofollowedBusinessNum);
        indexVo.setTofollowedCluesNum(tofollowedCluesNum);
        indexVo.setTofollowedBusinessNum(tofollowedBusinessNum);
        indexVo.setToallocatedCluesNum(toallocatedCluesNum);
        indexVo.setToallocatedBusinessNum(toallocatedBusinessNum);

        return indexVo;
    }

    /**
     * 线索转化龙虎榜
     * @param beginCreateTime
     * @param endCreateTime
     * @param deptId
     * @return
     */
    @Override
    public List<TopVo> salesStatistic(LocalDate beginCreateTime, LocalDate endCreateTime, Integer deptId) {
        LocalDateTime beginTime = LocalDateTime.of(beginCreateTime, LocalTime.MIN);
        LocalDateTime endTime = LocalDateTime.of(endCreateTime, LocalTime.MAX);

        HashMap map = new HashMap<>();
        map.put("beginTime",beginTime);
        map.put("endTime",endTime);
        List<TopSelectVo> indexStatisticsVos = reportMapper.selectSalesStatistic(map);

        List<TopVo> topVoList = indexStatisticsVos.stream().map(indexStatisticsVo -> {
            TopVo topVo = new TopVo();
            topVo.setCreate_by(indexStatisticsVo.getCreateBy());
            topVo.setDeptName(indexStatisticsVo.getDeptName());
            topVo.setNum(indexStatisticsVo.getUserNum());//用户线索转化条数
            topVo.setDep_id(indexStatisticsVo.getDeptId());
            topVo.setRadio(getRadio(indexStatisticsVo.getDeptNum(), Long.valueOf(indexStatisticsVo.getUserNum())));
            return topVo;
        }).collect(Collectors.toList());

        return topVoList;
    }

    /**
     * 商机转化龙虎榜
     *
     * @param beginCreateTime
     * @param endCreateTime
     * @param deptId
     * @return
     */
    @Override
    public List<TopVo> businessChangeStatistics(LocalDate beginCreateTime, LocalDate endCreateTime, Integer deptId) {
        LocalDateTime beginTime = LocalDateTime.of(beginCreateTime, LocalTime.MIN);
        LocalDateTime endTime = LocalDateTime.of(endCreateTime, LocalTime.MAX);

        HashMap map = new HashMap<>();
        map.put("beginTime",beginTime);
        map.put("endTime",endTime);
        List<TopSelectVo> indexStatisticsVos = reportMapper.selectBusinessChangeStatistics(map);

        List<TopVo> topVoList = indexStatisticsVos.stream().map(indexStatisticsVo -> {
            TopVo topVo = new TopVo();
            topVo.setCreate_by(indexStatisticsVo.getCreateBy());
            topVo.setDeptName(indexStatisticsVo.getDeptName());
            topVo.setNum(indexStatisticsVo.getUserNum());//用户线索转化条数
            topVo.setDep_id(indexStatisticsVo.getDeptId());
            topVo.setRadio(getRadio(indexStatisticsVo.getDeptNum(), Long.valueOf(indexStatisticsVo.getUserNum())));
            return topVo;
        }).collect(Collectors.toList());

        return topVoList;
    }





    // 新增线索数量统计
    @Override
    public LineChartVO getCluesStatistics(LocalDate beginCreateTime, LocalDate endCreateTime) {
        LocalDate begin=beginCreateTime; // 复制 起始位置
        // 1 :设置返回值的第一个参数
        // 日期集合
        List<String> xAxis = new ArrayList<>();
        while(!begin.equals(endCreateTime)){
            xAxis.add(begin.toString());
            begin=begin.plusDays(1);
        } //7


        // 日期对应每天结果集合
        // 2:查询每天的客户数
        List<LineSeriesVO> series = new ArrayList<>();

        // 定义当天新增线索集合
        LineSeriesVO userCount = new LineSeriesVO();
        List<Object> userNumbs=new ArrayList<>();
        userCount.setName("新增线索数");
        userCount.setData(null);

        // 定义线索总数集合
        LineSeriesVO  allCount= new LineSeriesVO();
        List<Object> allNumbs=new ArrayList<>();
        allCount.setName("线索总数");
        allCount.setData(null);



        // 遍历每天时间集合查数据
        xAxis.stream().forEach(day->{
            LocalDateTime beginTime = LocalDateTime.of(LocalDate.parse(day), LocalTime.MIN);// 当前开始日期
            LocalDateTime endTime = LocalDateTime.of(LocalDate.parse(day), LocalTime.MAX);// 当天结束时间
            // 查询当天新增线索数
            Long currentClubNums=tbClueMapper.getAddClueNums(beginTime,endTime);

            userNumbs.add(currentClubNums);
            // 查询线索总数

            LocalDateTime begTime=LocalDateTime.of(beginCreateTime,LocalTime.MIN);//总的起始日期
            Long currentallClubNums=tbClueMapper.getAddClueNums(begTime,endTime);

            allNumbs.add(currentallClubNums);

        });
        userCount.setData(userNumbs);
        allCount.setData(allNumbs);
        // 设置返回值的第二个参数
        series.add(userCount);
        series.add(allCount);



        // 返回值
        LineChartVO lineChartVO=new LineChartVO();
        lineChartVO.setxAxis(xAxis);
        lineChartVO.setSeries(series);

        return lineChartVO;
    }

    @Override
    public LineChartVO getontractStatistics(String beginCreateTime, String endTime) {
      if (beginCreateTime==null || endTime==null){
          throw new NullPointerException("查询统计客户列表，开始时间或截止时间为空！");
      }
        // 1 :设置返回值的第一个参数
        List<String> xAxis;
        // 日期集合
        try {
            xAxis =findDates(beginCreateTime,endTime);
        } catch (ParseException e) {
            throw new CustomException("时间解析异常",e);
        }
        // 2:查询每天的客户数
        List<LineSeriesVO> series = new ArrayList<>();

        // 定义当天新增线索集合
        LineSeriesVO userCount = new LineSeriesVO();
        List<Object> userNumbs=new ArrayList<>();
        userCount.setName("新增客户数");
        userCount.setData(null);

        // 定义线索总数集合
        LineSeriesVO  allCount= new LineSeriesVO();
        List<Object> allNumbs=new ArrayList<>();
        allCount.setName("客户总数");
        allCount.setData(null);
        LocalDateTime beginDateTime = LocalDateTime.of(LocalDate.parse(beginCreateTime), LocalTime.MIN);// 范围最早时间

        // 遍历每天时间集合查数据
        xAxis.stream().forEach(day->{
            // 查询当天新增客户数（合同签署完成）
            LocalDateTime beginCurrentTime = LocalDateTime.of(LocalDate.parse(day), LocalTime.MIN);// 当天最早时间
            LocalDateTime endCurrentTime = LocalDateTime.of(LocalDate.parse(day), LocalTime.MAX);// 当天最晚时间
            Long uCount=tbContractMapper.getontractStatistics(beginCurrentTime,endCurrentTime);
            userNumbs.add(uCount);
            // 查询客户总数
            Long alluCount=tbContractMapper.getontractStatistics(beginDateTime,endCurrentTime);
            allNumbs.add(alluCount);

        });
        userCount.setData(userNumbs);
        allCount.setData(allNumbs);
        // 设置返回值的第二个参数
        series.add(userCount);
        series.add(allCount);


        // 返回值
        LineChartVO lineChartVO=new LineChartVO();
        lineChartVO.setxAxis(xAxis);
        lineChartVO.setSeries(series);

        return lineChartVO;
    }

    /**
     * 学科客户分布
     * @param beginCreateTime
     * @param endTime
     * @return
     */
    @Override
    public List<SubjectVo> getSubjectStatistics(String beginCreateTime, String endTime) {
        LocalDateTime beginTime=LocalDateTime.of(LocalDate.parse(beginCreateTime),LocalTime.MIN);

        LocalDateTime endCreateTime=LocalDateTime.of(LocalDate.parse(endTime),LocalTime.MIN);

        List<SubjectVo> subjectVoList= tbClueMapper.getSubjectStatistics(beginTime,endCreateTime);

        return subjectVoList;
    }


    /**
     * 渠道统计饼图
     *
     * @param beginCreateTime
     * @param endCreateTime
     * @return
     */
    @Override
    public List<Map<String, Object>> chanelStatistics(LocalDate beginCreateTime, LocalDate endCreateTime) {
        LocalDateTime beginTime = LocalDateTime.of(beginCreateTime, LocalTime.MIN);
        LocalDateTime endTime = LocalDateTime.of(endCreateTime, LocalTime.MAX);

        List<Map<String, Object>> list = reportMapper.chanelStatistics(beginTime, endTime);

        return list;
    }

    /**
     * 活动统计饼图
     *
     * @param beginCreateTime
     * @param endCreateTime
     * @return
     */
    @Override
    public List<Map<String, Object>> activityStatistics(LocalDate beginCreateTime, LocalDate endCreateTime) {
        LocalDateTime beginTime = LocalDateTime.of(beginCreateTime, LocalTime.MIN);
        LocalDateTime endTime = LocalDateTime.of(endCreateTime, LocalTime.MAX);
        List<Map<String, Object>> list = reportMapper.activityStatistics(beginTime, endTime);
        return list;
    }

    /**
     * 渠道统计报表
     *
     * @param tbActivity
     * @return
     */
    @Override
    public List<ActivityStatisticsVo> activityStatisticsList(TbActivity tbActivity) {
        tbActivity.setStatus("2");
        List<TbActivity> activities = reportMapper.activityStatisticsList(tbActivity);
        Map<String, Object> map = tbActivity.getParams();
        ArrayList<ActivityStatisticsVo> list = new ArrayList<>();
        for (TbActivity activity : activities) {
            ActivityStatisticsVo activityStatisticsVo = new ActivityStatisticsVo();
            activityStatisticsVo.setChannel(activity.getChannel());
            activityStatisticsVo.setName(activity.getName());
            activityStatisticsVo.setInfo(activity.getInfo());
            activityStatisticsVo.setCode(activity.getCode());
            TbClue tbClue = new TbClue();
            tbClue.setActivityId(activity.getId());
            tbClue.setChannel(activity.getChannel());
            tbClue.setParams(map);
            Map<String, Object> clueCount = reportMapper.clueStatistics(tbClue);
            if (clueCount != null) {
                activityStatisticsVo.setCluesNum(Integer.parseInt(clueCount.get("cluesNum").toString()));
                if (clueCount.get("falseCluesnum")!=null){
                    activityStatisticsVo.setFalseCluesNum(Integer.parseInt(clueCount.get("falseCluesnum").toString()));
                }
                if (clueCount.get("businessNum")!=null){
                    activityStatisticsVo.setBusinessNum(Integer.parseInt(clueCount.get("businessNum").toString()));
                }
            }

            TbContract tbContract = new TbContract();
            tbContract.setActivityId(activity.getId());
            tbContract.setChannel(activity.getChannel());
            tbContract.setParams(map);
            Map<String,Object> contractCount = reportMapper.contractStatistics(tbContract);
            if (contractCount != null) {
                activityStatisticsVo.setCustomersNum(Integer.parseInt(contractCount.get("customersNum").toString()));
                if (contractCount.get("amount")==null){
                    activityStatisticsVo.setAmount(0.0);
                }else {
                    activityStatisticsVo.setAmount((Double) contractCount.get("amount"));
                }
                if (contractCount.get("cost")==null){
                    activityStatisticsVo.setCost(0.0);
                }else {
                    activityStatisticsVo.setCost((Double) contractCount.get("cost"));
                }
            }
            list.add(activityStatisticsVo);
        }

        return list;
    }
    /**
     *销售统计时间列表
     * @param beginCreateTime
     * @param endCreateTime
     * @return
     */
    @Override
    public LineChartVO salesStatistics( LocalDate beginCreateTime,  LocalDate endCreateTime)  {
        // 第一步获取日期列表
        List<String> dateList = null;
        try {
            dateList = findDates(beginCreateTime.toString(),endCreateTime.toString());
        } catch (ParseException e) {
            e.printStackTrace();
            throw new BaseException("字符串转换日期异常，在salesStatistics方法（ReportServiceImpl.java）");
        }

        LineChartVO lineChartVO = new LineChartVO();
        lineChartVO.setxAxis(dateList);

        ArrayList<LineSeriesVO> series = new ArrayList<>();
        HashMap map = new HashMap();// 定义参数集合
        List<Object> data = new ArrayList<>();
        for ( String date : dateList) {
            LocalDateTime beginTime = LocalDateTime.of(LocalDate.parse(date), LocalTime.MIN);
            LocalDateTime endTime = LocalDateTime.of(LocalDate.parse(date), LocalTime.MAX);
            map.put("beginTime",beginTime);
            map.put("endTime",endTime);
            Double data1 = reportMapper.salesStatistics(map);
            if (data1 == null) {
                data1 = 0.0;
            }
            data.add(data1);
        }
        LineSeriesVO lineSeriesVO = new LineSeriesVO();
        lineSeriesVO.setName("销售统计");
        lineSeriesVO.setData(data);
        series.add(lineSeriesVO);
        lineChartVO.setSeries(series);
        return lineChartVO;
    }
    /**
     * 部门统计报表
     * @param beginCreateTime
     * @param endCreateTime
     * @return
     */
    @Override
    public List<Map<String, Object>> deptStatisticsList( LocalDate beginCreateTime,  LocalDate endCreateTime) {
        LocalDateTime beginTime = LocalDateTime.of(beginCreateTime, LocalTime.MIN);
        LocalDateTime endTime = LocalDateTime.of(endCreateTime, LocalTime.MAX);
       List<Map<String, Object>> data =  reportMapper.deptStatisticsList(beginTime, endTime);
        for (Map<String, Object> datum : data) {
            Long deptId= (Long) datum.get("dept_id");
            if(deptId!=null){
                SysDept dept= reportMapper.selectDeptById(deptId);
                datum.put("deptName", dept.getDeptName());
            }
        }
        return data;
    }
    /**
     * 销售统计报表归属人
     * @param beginCreateTime
     * @param endCreateTime
     * @return
     */
    @Override
    public List<Map<String, Object>> ownerShipStatisticsList( LocalDate beginCreateTime,  LocalDate endCreateTime) {
        LocalDateTime beginTime = LocalDateTime.of(beginCreateTime, LocalTime.MIN);
        LocalDateTime endTime = LocalDateTime.of(endCreateTime, LocalTime.MAX);
        List<Map<String, Object>> data =reportMapper.ownerShipStatisticsList(beginTime, endTime);
        return data;
    }
    /**
     * 销售统计报表--归属渠道
     * @param beginCreateTime
     * @param endCreateTime
     * @return
     */
    @Override
    public List<Map<String, Object>> channelStatisticsList( LocalDate beginCreateTime,  LocalDate endCreateTime) {
        LocalDateTime beginTime = LocalDateTime.of(beginCreateTime, LocalTime.MIN);
        LocalDateTime endTime = LocalDateTime.of(endCreateTime, LocalTime.MAX);
        List<Map<String, Object>> data =  reportMapper.channelStatisticsList(beginTime, endTime);
        return data;
    }
}

